package com.lagou.edu.util;

import org.apache.commons.lang.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * @author: jie.zhao
 * @create: 2021/07/29 14:06
 */
public class DateUtil {


    public static final String datePattern = "yyyy-MM-dd";
    public static final String dateTimePattern = "yyyy-MM-dd HH:mm:ss";

    public static final String startDateTimePattern = "yyyy-MM-dd 00:00:00";
    public static final String dateTimePattern1 = "yyyy-MM-dd HH:mm";
    public static final String YYYYMM = "yyyyMM";

    public static final String YYYYMM2 = "yyyy/MM/dd";
    public static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static final DateTimeFormatter shortDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");


    private final static SimpleDateFormat sdfTime = new SimpleDateFormat(
            "yyyyMMddHHmmss");

    public static String getNow() {
        String start_time = "";
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date start = new Date();
            start_time = formatter.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }

    public static String getCurrentDay() {
        String start_time = "";
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            Date start = new Date();
            start_time = formatter.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }

    public static String getCurrentTime() {
        String start_time = "";
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date start = new Date();
            start_time = formatter.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }

    public static String getCurrentMonth() {
        String start_time = "";
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM");
            Date start = new Date();
            start_time = formatter.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }

    /**
     * 获取传入日期所在月份的开始日期
     *
     * @param date date
     * @return 日期所在月份的开始日期
     */
    public static Date getMonthStartDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DATE, cal.getActualMinimum(Calendar.DATE));
        return cal.getTime();
    }

    /**
     * 获取传入日期所在月份的结束日期
     *
     * @param date date
     * @return 日期所在月份的结束日期
     */
    public static Date getMonthEndDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
        return cal.getTime();
    }


    /**
     * 得到一天的最早的时间
     *
     * @param date one day
     * @return date
     */
    public static Date getDateFirstTime(Date date) {
        if (date == null) return null;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return new Date(cal.getTimeInMillis());
    }

    /**
     * 获取一天最晚的时间
     *
     * @param date one day
     * @return date
     */
    public static Date getDateLastTime(Date date) {
        if (date == null) return null;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 0);
        return new Date(cal.getTimeInMillis());
    }

    /**
     * 获取一天最晚的时间
     *
     * @return date
     */
    public static String getYmdLastTime(String ymd) {
        if (ymd.length() < 11) {
            ymd += " 23:59:59";
        }
        return ymd;
    }

    /**
     * 获取一天最早的时间
     *
     * @return date
     */
    public static String getYmdFirstTime(String ymd) {
        if (ymd.length() < 11) {
            ymd += " 00:00:00";
        }
        return ymd;
    }

    /**
     * 转换日期为字符串形式,
     *
     * @param date    日期
     * @param pattern 上面所列静态日期格式
     * @return string result
     */
    public static String convertDate2String(String pattern, Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        String result = "";
        if (date != null) {
            result = dateFormat.format(date);
        }
        return result;
    }


    /**
     * 将日期字符串格式化,
     *
     * @param strDate 日期字符串
     * @param pattern 上面所列静态日期格式
     * @return string result
     */
    public static String convertString2String(String pattern, String strDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Date date = convertString2DateTime(strDate);
        String result = "";
        if (date != null) {
            result = dateFormat.format(date);
        }
        return result;
    }

    /**
     * 将日期转换为字符串
     *
     * @param date date
     * @return string result
     */
    public static String convertDate2String(Date date) {
        return convertDate2String(datePattern, date);
    }

    /**
     * 将日期转换为字符串
     *
     * @param date date
     * @return string result
     */
    public static String convertDateTime2String(Date date) {
        return convertDate2String(dateTimePattern, date);
    }


    /**
     * 将日期字符串转为默认日期格式
     *
     * @param dateStr 日期字符串
     * @return date
     */
    public static Date convertString2Date(String dateStr) {
        return convertString2Date(datePattern, dateStr);
    }

    /**
     * 将时间字符串转为默认时间格式
     *
     * @param timeStr 时间字符串
     * @return Date
     */
    public static Date convertString2DateTime(String timeStr) {
        return convertString2Date(dateTimePattern, timeStr);
    }

    /**
     * 转换字符串为日期
     *
     * @param aMask   格式
     * @param strDate 日期字符串
     * @return date
     */
    public static Date convertString2Date(String aMask, String strDate) {
        if (StringUtils.isBlank(strDate)) return null;
        SimpleDateFormat df = new SimpleDateFormat(aMask);
        try {
            return new Date(df.parse(strDate).getTime());
        } catch (ParseException pe) {
            throw new RuntimeException("转换日期错误!");
        }
    }

    /**
     * 两个日期之间的天数
     *
     * @param sDate
     * @param eDate
     * @return date
     */
    public static String getDays(String sDate, String eDate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
            Date fDate = sdf.parse(sDate);
            Date oDate = sdf.parse(eDate);
            Calendar aCalendar = Calendar.getInstance();
            aCalendar.setTime(fDate);
            int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);
            aCalendar.setTime(oDate);
            int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);
            int days = day2 - day1;
            if (days > 0) {
                return days + "天";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "1天";
    }

    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(date1);
            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(date2);
            if (cal1 != null && cal2 != null) {
                return cal1.get(0) == cal2.get(0) && cal1.get(1) == cal2.get(1) && cal1.get(6) == cal2.get(6);
            }
        } else {
            throw new IllegalArgumentException("The date must not be null");
        }
        return false;
    }

    /**
     * 昨天的日期
     *
     * @return
     */
    public static String getYesterdayDateStr() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取某date 在i天之后的日期
     *
     * @param i
     * @return
     */
    public static Date getAfterDateIDays(Date date, int i) {

        Calendar c = Calendar.getInstance();

        c.setTime(date);

        c.add(Calendar.DAY_OF_MONTH, i);

        Date yesterday = c.getTime();

        return yesterday;
    }

    /**
     * 获取某date 在i天之后的日期
     *
     * @param i
     * @return
     */
    public static Date getAfterDateIMinute(Date date, int i) {

        Calendar c = Calendar.getInstance();

        c.setTime(date);

        c.add(Calendar.MINUTE, i);

        Date yesterday = c.getTime();

        return yesterday;
    }

    /**
     * 秒转换为时分秒
     *
     * @param date
     * @return
     */
    public static String getDate(Integer date) {
        if (date < 60) {
            return date + "秒";
        } else if (date > 60 && date < 3600) {
            int m = date / 60;
            int s = date % 60;
            return m + "分" + s + "秒";
        } else {
            int h = date / 3600;
            int m = (date % 3600) / 60;
            int s = (date % 3600) % 60;
            return h + "小时" + m + "分" + s + "秒";
        }

    }

    /**
     * 两个日期之间的天数
     *
     * @param fromDate
     * @param toDate
     * @return
     */
    public static Integer getDay(Date fromDate, Date toDate) {
        try {
            Calendar aCalendar = Calendar.getInstance();
            aCalendar.setTime(fromDate);
            int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);
            aCalendar.setTime(toDate);
            int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);
            int days = day2 - day1;
            return days;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 1;
    }

    //获取时间差方法
    public static String getTime(Date currentTime, Date firstTime) {
        String countTime = "";
        long diff = currentTime.getTime() - firstTime.getTime();//这样得到的差值是微秒级别
        long days = diff / (1000 * 60 * 60 * 24);
        long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); //获取时
        long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);  //获取分钟
        long s = (diff / 1000 - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60);//获取秒
        if (s > 0l) {
            countTime = s + "秒";
        }
        if (minutes > 0) {
            countTime = +minutes + "分" + countTime;
        }
        if (hours > 0) {
            countTime = hours + "小时" + countTime;
        }
        if (days > 0) {
            countTime = days + "天" + countTime;
        }
        return countTime;
    }

    /**
     * 时间转换为天小时分钟秒
     *
     * @param diff 毫秒
     * @return
     */
    public static String getTimeDescByTime(Long diff) {
        if (diff == 0L) {
            return "0";
        }
        String countTime = "";
        long days = diff / (1000 * 60 * 60 * 24);
        long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); //获取时
        long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);  //获取分钟
        long s = (diff / 1000 - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60);//获取秒
        if (s > 0l) {
            countTime = s + "秒";
        }
        if (minutes > 0) {
            countTime = +minutes + "分" + countTime;
        }
        if (hours > 0) {
            countTime = hours + "小时" + countTime;
        }
        if (days > 0) {
            countTime = days + "天" + countTime;
        }
        return countTime;
    }

    /**
     * 时间转换为小时分钟秒
     *
     * @param diff 毫秒
     * @return
     */
    public static String getTimeHourDescByTime(Long diff) {
        if (diff == 0L) {
            return "0";
        }
        String countTime = "";
        long days = 0;
        long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); //获取时
        long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);  //获取分钟
        long s = (diff / 1000 - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60);//获取秒
        if (s > 0l) {
            countTime = s + "秒";
        }
        if (minutes > 0) {
            countTime = +minutes + "分" + countTime;
        }
        if (hours > 0) {
            countTime = hours + "小时" + countTime;
        }
        if (days > 0) {
            countTime = days + "天" + countTime;
        }
        return countTime;
    }


    public static String getDayTime() {
        String start_time = "";
        try {
            Date start = new Date();
            start_time = sdfTime.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }

    public static String getDayTime1() {
        String start_time = "";
        try {
            Date start = new Date();
            start_time = sdfTime.format(start);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return start_time;
    }


    /**
     * 计算天差
     *
     * @param farDate
     * @param nearDate farDate > nearDate 返回正整数
     *                 farDate = nearDate 返回0
     *                 farDate < nearDate 返回负数
     * @return
     */
    public static int dateInterval(Date farDate, Date nearDate) {
        LocalDate farDateLocal = asLocalDate(farDate);
        LocalDate nearDateLocal = asLocalDate(nearDate);
        Long day = nearDateLocal.toEpochDay() - farDateLocal.toEpochDay();
        return Integer.parseInt(String.valueOf(day));
    }


    /**
     * 字符串转时间
     * 字符串 ymd hms
     *
     * @param dateStr
     * @return
     */
    public static Date parseYmdHms(String dateStr, DateTimeFormatter formatter) {
        LocalDateTime parse = LocalDateTime.parse(dateStr, formatter);
        ZonedDateTime zonedDateTime = parse.atZone((ZoneId.systemDefault()));
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 字符串转时间
     * 字符串 ymd hms
     *
     * @param dateStr
     * @return
     */
    public static Date parseYmd(String dateStr, DateTimeFormatter formatter) {
        LocalDate parse = LocalDate.parse(dateStr, formatter);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = parse.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }


    /**
     * 减n天
     *
     * @param date 日期
     * @param days 天数
     * @return
     */
    public static Date minusDays(Date date, long days) {
        LocalDateTime localDateTime = asLocalDateTime(date).minusDays(days);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }


    /**
     * 加n分钟
     *
     * @param date
     * @param minutes 分钟数
     * @return
     */
    public static Date plusMinutes(Date date, long minutes) {
        LocalDateTime localDateTime = asLocalDateTime(date).plusMinutes(minutes);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 加n分钟
     *
     * @param dateStr 日期格式：yyyy-MM-dd HH:mm:ss
     * @param minutes 分钟数
     * @return
     */
    public static String plusMinutes(String dateStr, long minutes) {
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, dateTimeFormatter).plusMinutes(minutes);
        return localDateTime.format(dateTimeFormatter);
    }

    /**
     * 减n分钟
     *
     * @param date
     * @param minutes 分钟数
     * @return
     */
    public static Date minusMinutes(Date date, long minutes) {
        LocalDateTime localDateTime = asLocalDateTime(date).minusMinutes(minutes);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }


    /**
     * Calls {@link #asLocalDate(Date, ZoneId)} with the system default time zone.
     */
    public static LocalDate asLocalDate(Date date) {
        return asLocalDate(date, ZoneId.systemDefault());
    }


    /**
     * Creates {@link LocalDate} from {@code java.util.Date} or it's subclasses. Null-safe.
     */
    public static LocalDate asLocalDate(Date date, ZoneId zone) {
        if (date == null) {
            return null;
        }

        if (date instanceof java.sql.Date) {
            return ((java.sql.Date) date).toLocalDate();
        } else {
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDate();
        }
    }


    /**
     * Calls {@link #asLocalDateTime(Date, ZoneId)} with the system default time zone.
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return asLocalDateTime(date, ZoneId.systemDefault());
    }


    /**
     * Creates {@link LocalDateTime} from {@code java.util.Date} or it's subclasses. Null-safe.
     */
    public static LocalDateTime asLocalDateTime(Date date, ZoneId zone) {
        if (date == null) {
            return null;
        }

        if (date instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) date).toLocalDateTime();
        } else {
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDateTime();
        }
    }


    public static Date parse(String dateStr) {
        LocalDateTime parse = LocalDateTime.parse(dateStr, dateTimeFormatter);
        ZonedDateTime zonedDateTime = parse.atZone((ZoneId.systemDefault()));
        return Date.from(zonedDateTime.toInstant());
    }

    public static long calBetweenTime(Date endDate) {
        long a = new Date().getTime();
        long b = endDate.getTime();
        long c = ((b - a) / 1000);
        return c;
    }

    public static void main(String[] args) {
        Date parse = parseYmd("2020-11-04", shortDateTimeFormatter);
        Date date = minusDays(parse, 30);
        System.out.println(convertDate2String(dateTimePattern, date));
    }
}


